home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 245_01 / lca41.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-10-26  |  11.1 KB  |  384 lines

  1.       
  2. /* (4,1) Linear Cellular Automaton    */
  3.  
  4. /* Reference:                */
  5. /*                    */
  6. /*    Kenneth E. Perry            */
  7. /*    Abstract Mathematical Art        */
  8. /*    BYTE                */
  9. /*    December, 1986            */
  10. /*    pages 181-192            */
  11.  
  12. /*    Copyright (C) 1987        */
  13. /*    Harold V. McIntosh        */
  14. /*    Gerardo Cisneros S.        */
  15.  
  16. /* G. Cisneros, 4.3.87                        */
  17. /* 10 April 1987 - modified for (4,2) [HVM]            */
  18. /* 26 April 1987 - Multiple menus [HVM]                */
  19. /* 28 April 1987 - back modified to (4,1) [HVM]            */
  20. /* 28 April 1987 - version for XVI Feria de Puebla [HVM]    */
  21.  
  22. # include <bdos.h>
  23.  
  24. # define COLGRAF     4  /* graph resolution */
  25. # define T80X25      3  /* text resolution */
  26. # define WHCYMAG     1  /* color quad for normal screen */
  27. # define AL        320  /* array length (screen width) */
  28. # define DS        10  /* number of distinct sums */
  29. # define DT        11  /* DS + 1 */
  30. # define NX         51    /* number of sample rules */
  31.  
  32. char xrule[] 
  33.  
  34.     "0001321200"  /* gliders, cycles, changing after 8000 gen */
  35.     "0003120121"  /* fishnet */
  36.     "0020303113"  /* glider from Perry's article */
  37.     "0023003220"  /* barriers and creepers */
  38.     "0003120210"  /* #22 with color runs */
  39.  
  40.     "0010322132"  /* almost a barrier */
  41.     "0012130032"  /* wiggles back and forth */
  42.     "0012130000"  /* no gliders but class iv */
  43.     "0303200131"  /* varicolored cells, blue barriers */
  44.     "0031202003"  /* wiggles */
  45.  
  46.     "0031202023"  /* red and black */
  47.     "0133330222"  /* checkerboard */
  48.     "0331202003"  /* insettled */
  49.     "0101212303"  /* reds fight greens */
  50.     "0120133230"
  51.  
  52.     "0123003220"  /* barrier & irregular creeper */
  53.     "0123022233"  /* green-balck cells */
  54.     "0131123113"  /* gliders */
  55.     "0202311130"  /* marvellous stripes */
  56.     "0203011100"  /* open latticework */
  57.  
  58.     "0203101121"  /* black vs red-blue */
  59.     "0203210031"  /* */
  60.     "0223112303"  /* */
  61.     "0223112313"  /* */
  62.     "0230130120"  /* cycles and wiggles */
  63.  
  64.     "0231123002"  /* almost a bouncing shuttle */
  65.     "0231123003"  /* nice variant */
  66.     "1002120031"  /* mottled */
  67.     "1012333130"  /* uniform */
  68.     "1120311321"  /* pea soup */
  69.  
  70.     "1131301023"  /* threads */
  71.     "1200003011"  /* gliders and walls */
  72.     "1333011002"  /* stripey */
  73.     "2011033320"  /* */
  74.     "3020110010"  /* watch the lattice develop */
  75.  
  76.     "3021331332"  /* oodles of triangles */
  77.     "3100323113"  /* pntd crct bd */
  78.     "3111203022"  /* interesting barriers */
  79.     "3120111330"  /* varicolored cells w/blue barrier */
  80.     "3232221023"  /* interesting barriers */
  81.  
  82.     "3301123211"  /* black stripe */
  83.     "3330121210"  /* varied */
  84.     "3331202110"  /* venetian blind */
  85.     "3332020321"  /* checkered table cloth */
  86.     "3332121001"  /* small cells */
  87.  
  88.     "3332320120"  /* zebra glider */
  89.     "3333120121"  /* another glider */
  90.     "3333120122"  /* two speeds of glider */
  91.     "3333122101"  /* aggressive green & stripes */
  92.     "3333210120"  /* slow gliders */
  93.  
  94.     "3333220113"  /* triangles vs checkers */
  95.  
  96.     ;
  97.  
  98. char  xx[4], rule[DT];
  99. int   arule[DS], arr1[AL], arr2[AL];
  100.  
  101. main()
  102. {
  103. int c, i, jj, n;
  104. int  more = 'r';
  105.  
  106.     videopalette(WHCYMAG);                /* white/cyan/magenta */
  107.  
  108.     tuto();
  109.     while (!kbdst()) jj=rand();                /* wait for keypress */
  110.     c=kbdin();                        /* ignore it */
  111.     jj=rand()%NX;
  112.     for (i=0; i<DS; i++) rule[i] = xrule[DS*jj+i];    /* random sample rule */
  113.     rule[DS]=0;
  114.     for (i=0; i<AL; i++) {                /* random initial array */
  115.     if (i%4 == 0) c=rand();
  116.     arr1[i]=c&3; c>>=2;};
  117.     videomode(T80X25);
  118.     videoscroll(3,0,4,71,0,3);                /* menu on blue background */
  119.     videoscroll(16,0,21,71,0,3);
  120.     xmenu(jj+1);                    /* show initial rule */
  121.  
  122.     while (more!='n') {                    /* execute multiple runs */
  123.     rmenu();
  124.     lmenu();
  125.     while (0<1) {                    /* set up one run */
  126.     c=kbdin();
  127.     if (c=='g') break;                    /* go draw graph */
  128.     if (c=='q') more='n';                /* quit for good */
  129.     if (more=='n') break;
  130.     switch (c) {
  131.         case 'r':                    /* edit rule */    
  132.         xblnk();
  133.         edrule();
  134.         videocursor(0,3,0);
  135.         rmenu();
  136.         break;
  137.         case 'l':                    /* edit cell string */
  138.         xblnk();
  139.         edline();
  140.         videocursor(0,3,0);
  141.         lmenu();
  142.         break;
  143.         case '#':                    /* read stored rule */
  144.         xmenu(NX);
  145.         n=DS*((i=lim(1,numin(0),NX))-1);
  146.         xmenu(i);
  147.         for (i=0; i<DS; i++) rule[i] = xrule[n+i];
  148.         rmenu();
  149.             break;
  150.         case 'u':
  151.         xblnk();
  152.         for (i=0; i<AL; i++) arr1[i]=0;
  153.         arr1[AL/4]=1;
  154.             arr1[AL/2]=2;
  155.             arr1[(3*AL)/4]=3;
  156.         lmenu();
  157.             break;
  158.     case 'x':                    /* random rule */
  159.         xblnk();
  160.             for (i=0; i<DS; i++) {
  161.             if (i%4 == 0) c = rand();
  162.             rule[i] = '0'+(c & 3);
  163.             c >>= 2;
  164.             };
  165.         rmenu();
  166.         break;
  167.     case 'y':                    /* random line */
  168.         xblnk();
  169.         for (i=0; i<AL; i++) {
  170.             if (i%4 == 0) c = rand();
  171.             arr1[i] = c & 3;
  172.             c >>= 2;
  173.             };
  174.             lmenu();
  175.         break;
  176.         default: break;
  177.         };
  178.     };
  179.     if (more=='n') break;
  180.     do {
  181.     evolve(rule);
  182.     videocursor(0,0,0);
  183.     scrstr("More?");
  184.     videocursor(0,0,30);
  185.     scrstr("y/n/cr");
  186.     more=kbdin();
  187.     } while (more=='\015');
  188.     videomode(T80X25);                    /* reset the screen */
  189.     if (more=='n') break;
  190.     };
  191. }    
  192.  
  193. edrule()                        /* edit the rule */
  194. {
  195. char c;
  196. int  i;
  197.  
  198.     videocursor(0,1,6);                    /* get the rule */
  199.     i=0;
  200.     while (i<DS) {
  201.         videoputc(rule[i],2);
  202.         videoputc('\010',1);
  203.         c = kbdin();
  204.         if (c == '\015') break;
  205.         switch (c) {
  206.         case '0':  case '1': case '2': case '3':    /* state */
  207.             rule[i++] = c;
  208.             videoputc(c,1);
  209.             break;
  210.         case ' ':                    /* space = advance */
  211.             videoputc(rule[i++],1);
  212.             break;
  213.         case '\010':                    /* backspace */
  214.             if (i==0) break;
  215.             videoputc(rule[i--],1);
  216.             videoputc(c,1);
  217.             videoputc(c,1);
  218.             break;
  219.     default: break;
  220.         };
  221.     };
  222. }
  223.  
  224. edline() {                        /* edit the line */
  225.  
  226. char c;
  227. int  i, j, k, ii, jj;
  228.  
  229.     videocursor(0,16,0);
  230.     scrstr("insert states using 0, 1, 2, 3");
  231.     videocursor(0,17,0);
  232.     scrstr("move cursor with n(north), s(south), e(east), w(west), or");
  233.     videocursor(0,18,0);
  234.     scrstr("with keyboard arrows. Space, backspace move right and left.");
  235.     videocursor(0,19,0);
  236.     scrstr("( seeks left margin, < absolutely, { up one line, [ down one line");
  237.     videocursor(0,20,0);
  238.     scrstr(") seeks right margin, > absolutely, } up one line, ] down one line");
  239.     videocursor(0,21,0);
  240.     scrstr("carriage return exits");
  241.     jj=4;
  242.     ii=1;
  243.     while (0<1) {
  244.     ii=lim(1,ii,40);
  245.     jj=lim(1,jj,8);
  246.     j=jj-1;
  247.     i=ii-1;
  248.     videocursor(0,j+6,i);
  249.     c=kbdin();
  250.     if (c == '\015') {videoscroll(16,0,21,70,0,3); break;};
  251.     switch (c) {
  252.     case '0':  case '1': case '2': case '3':        /* enter  state */
  253.         arr1[40*j+i] = c-'0';
  254.     ii++;
  255.     break;
  256.     case 's': case '\012': case '\320':          jj++; break;    /* down - next line */
  257.     case 'n': case '\013': case '\310':          jj--; break;    /* up   - last line */
  258.     case 'e': case '\014': case '\315': case ' ': ii++; break;    /* space = advance  */
  259.     case 'w': case '\010': case '\313':          ii--; break;    /* backspace */
  260.     case '<': ii=1;  jj=1;  break;  /* absolute left */
  261.     case '{': ii=1;  jj--;  break;  /* left one row up */
  262.     case '(': ii=1;         break;  /* left this row */
  263.     case '[': ii=1;  jj++;  break;  /* left next row */
  264.     case '>': ii=40; jj=40; break;  /* absolute right */
  265.     case '}': ii=40; jj--;  break;  /* right one row up */
  266.     case ')': ii=40;        break;  /* right this row */
  267.     case ']': ii=40; jj++;  break;  /* right next row */
  268.     default: break;
  269.         };
  270.     videocursor(0,j+6,0);
  271.     for (k=0; k<40; k++) videoputc('0'+arr1[40*j+k],1);
  272.     };
  273. }
  274.  
  275. evolve(rule)                        /* display a screen of evolution */
  276. char *rule;
  277. {
  278. int i, j, sum, sum0, sum1;
  279.  
  280.     videomode(COLGRAF);                    /* erase the screen */
  281.     videocursor(0,0,0);                    /* top text line */
  282.     scrstr("Rule: ");
  283.     scrstr(rule);
  284.     for (i=0; i<DS; i++) {arule[i] = rule[i]-'0';}
  285.     for (j=8; j<200; j++) videodot(j,AL-1,2);
  286.     for (j=8; j<200; j++) {                /* evolve for 192 generations */
  287.         sum0 = arr1[AL-1] + arr1[0] + arr1[1];
  288.         arr2[0] = arule[sum0];
  289.         for (i=1; i<AL-1; i++) {
  290.             sum = arr1[i-1] + arr1[i] + arr1[i+1];
  291.             arr2[i] = arule[sum];
  292.             };
  293.         sum1 = arr1[AL-2] + arr1[AL-1] + arr1[0];
  294.         arr2[AL-1] = arule[sum1];
  295.         for (i=0;  i<AL; i++) {videodot(j,i,arr1[i]); arr1[i] = arr2[i];};
  296.     if (kbdst()) {kbdin(); break;};
  297.         }
  298. }
  299.  
  300. tuto()                            /* tutorial and Help screen */
  301. {
  302.     videomode(T80X25);
  303.     videocursor(0,2,0);
  304.     scrstr("<Copyright (C) 1987 - H.V. McIntosh, G. Cisneros S.>");
  305.     videocursor(0,4,0);
  306.     scrstr("          *** LIFE in One Dimension ***");
  307.     videocursor(0,6,0);
  308.     scrstr("Four States - Black(0), Cyan(1), Magenta(2), White(3).");
  309.     videocursor(0,8,0);
  310.     scrstr("First neighbors - one on each side, three altogether.");
  311.     videocursor(0,10,0);
  312.     scrstr("Totalistic transition rule - random, edited, or stored.");
  313.     videocursor(0,12,0);
  314.     scrstr("Initial Cellular Array - random, edited, or patterned.");
  315.     videocursor(0,14,0);
  316.     scrstr("Some rules are fragile and require several tries before");
  317.     videocursor(0,15,0);
  318.     scrstr("manifesting an interesting evolutionary pattern.");
  319.     videocursor(0,17,0);
  320.     scrstr("Use any key to terminate a display in progress.");
  321.     videocursor(0,21,0);
  322.     scrstr("now, press any key to continue ...");
  323. }
  324.  
  325. rmenu() {                        /* rule menu */
  326.     videocursor(0,0,0);
  327.     scrstr("      0..1..2..3");
  328.     videocursor(0,1,0);
  329.     scrstr("Rule: "); scrstr(rule);
  330.     videocursor(0,3,0);
  331.     scrstr("    r(rule), l(line), #nn(stored rule), g(graph), q(quit)");
  332.     videocursor(0,4,0);
  333.     scrstr("             x(random rule), y(random line), u(unit line).");
  334.     videocursor(0,3,0);
  335.     }
  336.  
  337. lmenu() {                        /* line menu */
  338. int i, j;
  339.     for (j=0; 40*j<AL; j++) {
  340.     videocursor(0,6+j,0);
  341.     for (i=0; i<40; i++) videoputc('0'+arr1[40*j+i],1);
  342.     }
  343.     videocursor(0,3,0);
  344.     }
  345.  
  346. xmenu(n) int n;                        /* display rule number */
  347. {int i, nn;  
  348.     nn=sprintf(xx,"%3d",n);
  349.     videocursor(0,1,30);
  350.     for (i=0; i<nn; i++) videoputc(xx[i],1);
  351.     videocursor(0,1,30);
  352. }
  353.  
  354. xblnk() {                        /* clear rule number */
  355.     videocursor(0,1,30);
  356.     scrstr("    ");
  357.     videocursor(0,3,0);
  358. }
  359.  
  360. int lim(i,j,k)
  361. int i, j, k;                        /* limit j to interval (i,k) */
  362.     {if (i>=j) return i; if (k<=j) return k; return j;}
  363.  
  364. scrstr(s)                        /* write a string in graphics mode */
  365. char *s;
  366. { for (; *s != '\0'; s++) videoputc(*s,1); }
  367.  
  368. int kbdst()                        /* keyboard status */
  369. {return(bdos(11) & 0xFF);}
  370.  
  371. kbdin() {                        /* direct keyboard input, no echo */
  372. int c;
  373.     if ((c = bdos(7) & 0xFF) == '\0') c = (bdos(7) & 0xFF) | 0x80;
  374.     return(c);
  375. }
  376.  
  377. int numin(n)                        /* read number from keyboard */
  378. int n; {char c;
  379.     c=kbdin();
  380.     if (c>='0'&&c<='9') return(numin(10*n+(c-'0'))); else return(n);
  381. }
  382.  
  383. /* end */
  384.